-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Use ranges to define versions of dependencies for converged components #17499
Conversation
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit ffab59c:
|
Asset size changesSize Auditor did not detect a change in bundle size for any component! Baseline commit: c49525b95c315995c323e2b7efe50c637ceb539e (build) |
Perf AnalysisNo significant results to display. All results
Perf Analysis (Fluent)Perf comparison
Perf tests with no regressions
|
|
||
Use semver ranges to define production dependencies for our customers. Exact versions can be used in non-distributed code (build and infra tools). | ||
|
||
_Optionally_: Distribute with packages `VERSIONS` file that will contain versions of dependencies that are used on our side in machine readable format that can be potentially used by customers in their pipelines. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's not be too hasty, as I said will follow up with OSS CELA on the actual requirements ASAP
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CELA conclusion: we can only run enhanced license scan on specific versions we use, so this idea could work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By "this idea" do you mean the VERSIONS file? How would that work from a consumer's perspective, specifically re: legal? (Feel free to respond on teams if needed.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My initial idea was that we can implement a Webpack plugin that will ensure that included dependencies match versions defined in VERSIONS
file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems fine to me in general but I'd appreciate clarification on a couple nuances.
|
||
Thus a single package gets included multiple times in a Webpack bundle due to different package versions. This situation will happen without any warning, resulting in extra bloat in consumer's bundle and may lead to hard-to-find bugs. | ||
|
||
It's also harder for consumers in this case to consume security patches, for example `lodash@4.17.20` contains [a security vulnerability](https://snyk.io/vuln/SNYK-JS-LODASH-1018905) but this version will be inside consumer's application without additional movements from their side. If we will use a caret ("lodash": "^4.17.20") only a single version (a latest in a range) will be installed: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we will use a caret ("lodash": "^4.17.20") only a single version (a latest in a range) will be installed
Just a heads up, this is not necessarily true--if a dep on lodash@^4.17.20
resolved to 4.17.20
already exists in the lockfile, and that semver spec is still referenced by another package, yarn may add a separate entry for lodash@^4.17.21
=> 4.17.21
instead of resolving both to 4.17.21
.
(Doesn't affect the proposal since this is an issue with yarn in general, but I wanted to call it out for awareness.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, you're totally right 👍 But with ranges we can at least deduplicate dependencies manually or via tools (yarn-deduplicate
for Yarn v1 or yarn dedupe
for V2).
|
||
## Detailed Design or Proposal | ||
|
||
Use semver ranges to define production dependencies for our customers. Exact versions can be used in non-distributed code (build and infra tools). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple possible issues/nuances here that I wonder if we should include in the proposal re: different versions for production and dev dependencies:
- How do we set this up with syncpack? My first idea would be something like this (supposing
converged1
andconverged2
depend onlodash@^4.17.21
, whereas other packages have a specific version in devDependencies):
{
"packages": ["@fluentui/converged1", "@fluentui/converged2"],
"dependencies": ["lodash"]
}
- How do we guarantee that yarn resolves the production dep to the same version as the dev dep within our repo? Without tooling enforcement, it's entirely possible that yarn could choose to resolve the two versions differently. My first idea (which probably won't work, see below) is this. (The leading
**
is necessary to make resolutions work for packages within the workspace.)
{
"resolutions": {
"**/@fluentui/*/lodash": "4.17.21"
}
}
However this might not work because the resolutions spec says a single *
is not supported (would probably be good to test it in case the implementation is different). **/@fluentui/**/lodash
should be supported, but that would resolve all nested tools' lodash deps to a specific version, which might be a problem. So we'd probably have to figure out some other approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do we set this up with syncpack?
Do you mean our repo, correct? Can please expand a bit more there, I did not get the problem.
How do we guarantee that yarn resolves the production dep to the same version as the dev dep within our repo?
IMO we should not guarantee this, for example: we don't restrict people to use the same version of React as in our repo, why it should be different for other dependencies? It means that we should be accurate in choosing dependencies, they should follow semver.
However, resolutions
can be and should be used by customers for legal issues. I tried your approach with resolutions
on Yarn v1:
{
"dependencies": {
"@fluentui/react-components": "^9.0.0-alpha.36",
"@popperjs/core": "^2.9.2"
},
"resolutions": {
"**/@fluentui/*/@popperjs/core": "2.8.0"
}
}
This results in two versions installed:
"@popperjs/core@2.8.0", "@popperjs/core@~2.4.3":
version "2.8.0"
"@popperjs/core@^2.9.2":
version "2.9.2"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do we set this up with syncpack?
Do you mean our repo, correct? Can please expand a bit more there, I did not get the problem.
With syncpack you're only allowed to depend on one semver spec for a given dep, unless you set up a versionGroups
entry allowing certain packages to use a different version spec for that dep.
How do we guarantee that yarn resolves the production dep to the same version as the dev dep within our repo?
IMO we should not guarantee this, for example: we don't restrict people to use the same version of React as in our repo, why it should be different for other dependencies? It means that we should be accurate in choosing dependencies, they should follow semver.
I meant within our repo, not from a customer standpoint. Yarn may sometimes decide to resolve foo@^1.0.0
(production dep) and foo@1.1.0
(dev dep) differently, resulting in duplicates within our build process, which is a significant part of the problem @Hotell was trying to resolve to begin with.
The resolutions suggestion was also meant to be used within our repo. (If it doesn't work as I wrote it, we could do some more experimenting.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ecraig12345 so this thread is related only to our repo correct?
With syncpack you're only allowed to depend on one semver spec for a given dep, unless you set up a versionGroups entry allowing certain packages to use a different version spec for that dep.
As I know @Hotell proposed to move out all dev dependencies to the root package.json
. If we will do this and ignore the root package.json
in syncpack, will it solve the issue?
Yarn may sometimes decide to resolve
foo@^1.0.0
(production dep) andfoo@1.1.0
(dev dep) differently, resulting in duplicates within our build process, which is a significant part of the problem @Hotell was trying to resolve to begin with.
Honestly I don't think that I understand what solves usage of exact versions for dev dependencies.
- we are sure that we are using an exact version, for example
webpack@5.0.0
- it does not solve duplicate dependencies as
storybook
may depend onwebpack@^5.1.0
- this results in two entries for
webpack
(and potentially its sub dependencies) in ouryarn.lock
Are these statements correct?
|
||
Use semver ranges to define production dependencies for our customers. Exact versions can be used in non-distributed code (build and infra tools). | ||
|
||
_Optionally_: Distribute with packages `VERSIONS` file that will contain versions of dependencies that are used on our side in machine readable format that can be potentially used by customers in their pipelines. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By "this idea" do you mean the VERSIONS file? How would that work from a consumer's perspective, specifically re: legal? (Feel free to respond on teams if needed.)
Bump, sounds like next week we can close this up @layershifter? |
Yes, merging this as I don't see blocking items. @ecraig12345 we can continue conversation on this PR or in offline 😉 |
@layershifter I understand wanting to move things forward, but in the future I'd really appreciate direct confirmation (or a chance on business hours to see and respond to comments) before going ahead with merging despite outstanding comments. I didn't block the PR because I agree with the overall concept, but the problem of how to prevent duplicates locally is very important for maintaining reliable, predictable builds and dev experience. |
This RFC proposes to continue use caret (
^
) and tilde (~
) to define version ranges for production dependencies of converged packages.Please check rendered preview.